﻿//-----------------------------------------------------------------------
// <copyright file="MessageDisplayHelpers.cs" company="AFS">
// Copyright (c) AFS. All rights reserved.
//
//    This file is part of Chatbox.
//
//    Chatbox is free software: you can redistribute it and/or modify
//    it under the terms of the GNU Lesser General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    any later version.
//
//    Chatbox is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//    GNU Lesser General Public License for more details.
//
//    You should have received a copy of the GNU Lesser General Public License
//    along with Chatbox. If not, see http://www.gnu.org/copyleft/lesser.html
// </copyright>
//----------------------------------------------------------------------- 

namespace ChatBox.UI.MessageDisplay
{
    using System;
    using System.Globalization;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;

    using ChatBox.DomainObjects.XmlFeedObjects;
    using ChatBox.XamlUtility;

    /// <summary>
    /// Helper emthods and data for message display
    /// </summary>
    public static class MessageDisplayHelpers
    {
        /// <summary>
        /// Format to use when displaying date and time of message
        /// </summary>
        public const string MessageDisplayDateTimeFormat = "dd mm yy hh:mm";

        /// <summary>
        /// Format to use when displaying time of message
        /// </summary>
        public const string MessageDisplayTimeFormat = "hh:mm";

        /// <summary>
        /// Format a datetime for display
        /// </summary>
        /// <param name="date">the date to format</param>
        /// <param name="dateTimeDisplay">show the date</param>
        /// <returns>the string representaion of the date</returns>
        public static string FormatForDisplay(this DateTime date, DateTimeDisplay dateTimeDisplay)
        {
            return date.ToString(dateTimeDisplay == DateTimeDisplay.DateTime ? "g" : "t", CultureInfo.CurrentCulture);
        }

        /// <summary>
        /// Standard DateFormat format
        /// </summary>
        /// <param name="message">the message to format</param>
        /// <param name="dateTimeDisplay">show the date or date and time</param>
        /// <returns>the xaml content</returns>
        public static Inline DateFormat(Message message, DateTimeDisplay dateTimeDisplay)
        {
            Run dateRun = new Run(message.Sent.FormatForDisplay(dateTimeDisplay) + " ");
            return new Bold(dateRun);
        }

        /// <summary>
        /// Standard sender format
        /// </summary>
        /// <param name="message">the message to format</param>
        /// <param name="hyperlinkContext">the hyperlink context</param>
        /// <returns>the xaml content</returns>
        public static Inline SenderFormat(Message message, HyperlinkContext hyperlinkContext)
        {
            return SenderFormatInternal(message.From.Text, message.From.NodeId, hyperlinkContext);
        }

        /// <summary>
        /// format the group "from" field
        /// </summary>
        /// <param name="message">the message to format</param>
        /// <param name="hyperlinkContext">the hyperlink context</param>
        /// <param name="formatOptions">the format Options</param>
        /// <returns>the xaml content</returns>
        public static Inline GroupFrom(Message message, HyperlinkContext hyperlinkContext, FormatOptions formatOptions)
        {
            Span span = new Span();
            span.Inlines.Add(new Run("("));

            Hyperlink groupHyperlink = new Hyperlink(new Run(message.Group.Text));
            groupHyperlink.NavigateUri = new Uri(hyperlinkContext.SitePrefix + "/node/" + message.Group.NodeId);
            hyperlinkContext.SetContextOnHyperlink(groupHyperlink);
            span.Inlines.Add(groupHyperlink);

            if (formatOptions.ShowSendPrivateMessageButton)
            {
                span.Inlines.Add(PrivateMessageToUserButton(message.Group, formatOptions));
            }

            span.Inlines.Add(new Run(") "));

            return span;
        }

        /// <summary>
        /// Sender format in caps
        /// </summary>
        /// <param name="message">the message to format</param>
        /// <param name="hyperlinkContext">the hyperlink context</param>
        /// <returns>the xaml content</returns>
        public static Inline SenderFormatCaps(Message message, HyperlinkContext hyperlinkContext)
        {
            return SenderFormatInternal(message.From.Text.ToUpper(CultureInfo.InvariantCulture), message.From.NodeId, hyperlinkContext);
        }

        /// <summary>
        /// Generate a button the send a private message to this user
        /// </summary>
        /// <param name="link">the user details</param>
        /// <param name="formatOptions">formatting options</param>
        /// <returns>the generated button</returns>
        public static Span PrivateMessageToUserButton(Link link, FormatOptions formatOptions)
        {
            Button privateMessageButton = new Button();
            privateMessageButton.Style = formatOptions.SendPrivateMessageButtonStyle;

            if (link.GroupType == GroupType.UserGroup)
            {
                privateMessageButton.ToolTip = "Message to group " + link.Text;
            }
            else
            {
                privateMessageButton.ToolTip = "Private message to " + link.Text;                
            }

            if (formatOptions.SendPrivateMessageButtonHandler != null)
            {
                privateMessageButton.Click +=
                        (o, r) => formatOptions.SendPrivateMessageButtonHandler(privateMessageButton, link);
            }

            // The button looks better aligned at the bottom, like this
            Span verticallyAlignedSpan = new Span();
            verticallyAlignedSpan.Inlines.Add(privateMessageButton);
            verticallyAlignedSpan.BaselineAlignment = BaselineAlignment.Bottom;

            return verticallyAlignedSpan;
        }

        /// <summary>
        /// Create the message delete button
        /// </summary>
        /// <param name="message">the message to delete</param>
        /// <param name="formatOptions">format options</param>
        /// <returns>the delete button</returns>
        public static Span DeleteMessageButton(Message message, FormatOptions formatOptions)
        {
            Button deleteMessageButton = new Button();
            deleteMessageButton.Style = formatOptions.DeleteMessageButtonStyle;
            deleteMessageButton.VerticalAlignment = VerticalAlignment.Center;
            deleteMessageButton.ToolTip = "Delete message";

            if (formatOptions.DeleteMessageButtonHandler != null)
            {
                deleteMessageButton.Click +=
                        (o, r) => formatOptions.DeleteMessageButtonHandler(deleteMessageButton, message);
            }

            // The button looks better aligned at the bottom, like this
            Span verticallyAlignedSpan = new Span();
            verticallyAlignedSpan.Inlines.Add(deleteMessageButton);
            verticallyAlignedSpan.BaselineAlignment = BaselineAlignment.Bottom;

            return verticallyAlignedSpan;
        }

        /// <summary>
        /// Sender format
        /// </summary>
        /// <param name="userName">the user name to show</param>
        /// <param name="userNodeId">the user node id to link to</param>
        /// <param name="hyperlinkContext">the hyperlink context</param>
        /// <returns>the xaml content</returns>
        private static Inline SenderFormatInternal(string userName, int userNodeId, HyperlinkContext hyperlinkContext)
        {
            Hyperlink fromLink = new Hyperlink(new Run(userName));
            fromLink.NavigateUri = new Uri(hyperlinkContext.SitePrefix + "/node/" + userNodeId);
            hyperlinkContext.SetContextOnHyperlink(fromLink);

            return fromLink;
        }
    }
}